##########################################
## Copyright 2012-2014 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

from PyQt4 import QtGui, QtCore


class QLevelPlotter(QtGui.QWidget):

    DB_MIN = -40
    DB_MAX = 0
    DB_CLIP = 0

    def __init__(self, parent):
        super(QLevelPlotter, self).__init__(parent)

        self.grad = QtGui.QLinearGradient()
        self.grad.setColorAt(0, QtGui.QColor(0, 255, 0))         # Green
        self.grad.setColorAt(0.5, QtGui.QColor(255, 255, 0))     # Yellow
        self.grad.setColorAt(1, QtGui.QColor(255, 0, 0))         # Red

        self.reset()

    def reset(self):
        self.levels = [self.DB_MIN, self.DB_MIN]
        self.decPeak = [self.DB_MIN, self.DB_MIN]
        self.clipping = {}
        self.repaint()

    @QtCore.pyqtSlot(list, list)
    def plot(self, levels, decPeak):
        if(len(levels) == 1):
            self.levels = levels * 2
            self.decPeak = decPeak * 2
        else:
            self.levels = levels
            self.decPeak = decPeak

        self.repaint()

    def paintEvent(self, e):
        if not self.visibleRegion().isEmpty():
            # Stretch factor
            mul = (self.height() - 4)
            mul /= (self.DB_MAX - self.DB_MIN)

            levels = []
            for n, level in enumerate(self.levels):
                if level > self.DB_CLIP:
                    self.clipping[n] = True

                if level < self.DB_MIN:
                    level = self.DB_MIN
                elif level > self.DB_MAX:
                    level = self.DB_MAX

                levels.append(round((level - self.DB_MIN) * mul))

            decPeaks = []
            for decPeak in self.decPeak:
                if decPeak < self.DB_MIN:
                    decPeak = self.DB_MIN
                elif decPeak > self.DB_MAX:
                    decPeak = self.DB_MAX

                decPeaks.append(round((decPeak - self.DB_MIN) * mul))

            qp = QtGui.QPainter()
            qp.begin(self)
            qp.setBrush(QtGui.QColor(0, 0, 0, 0))

            xpos = 0
            xdim = self.width() / len(levels)

            for n in range(len(levels)):
                level = levels[n]
                decPeak = decPeaks[n]

                # Maximum "level-rect" size
                maxRect = QtCore.QRect(xpos,
                                       self.height() - 2,
                                       xdim - 2,
                                       2 - self.height())

                # Set QLinearGradient start and final-stop position
                self.grad.setStart(maxRect.topLeft())
                self.grad.setFinalStop(maxRect.bottomRight())

                # Draw level (audio level in dB)
                rect = QtCore.QRect(xpos, self.height() - 2, xdim - 2, -level)
                qp.fillRect(rect, self.grad)

                # Draw decay peak
                decRect = QtCore.QRect(xpos,
                                       (self.height() - 3) - decPeak,
                                       xdim - 2,
                                       2)
                qp.fillRect(decRect, self.grad)

                # Draw Borders
                if self.clipping.get(n, False):
                    qp.setPen(QtGui.QColor(200, 0, 0))
                else:
                    qp.setPen(QtGui.QColor(100, 100, 100))

                qp.drawRect(maxRect)

                xpos += xdim

            qp.end()
